package org.example.fastproject.core.security;

import cn.hutool.core.util.StrUtil;
import lombok.AllArgsConstructor;
import lombok.Data;
import org.example.fastproject.core.bean.SysUserDetails;
import org.example.fastproject.core.utils.JwtUtil;
import org.example.fastproject.web.sys.model.vo.user.UserLoginVo;
import org.example.fastproject.web.sys.model.vo.user.UserVo;
import org.example.fastproject.web.sys.service.SysCacheService;
import org.example.fastproject.web.sys.service.SysPermissionService;
import org.example.fastproject.web.sys.service.SysUserService;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.util.PathMatcher;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.List;
import java.util.Objects;

/**
 * @Author 王海舟
 * @Date 2023/1/18 12:40
 * @PackageName:org.example.fastproject.core.security
 * @ClassName: TokenAuthenticationFilter
 * @Description: token认证过滤器
 * @Version 1.0
 */
@Data
@AllArgsConstructor
public class TokenAuthenticationFilter extends OncePerRequestFilter {
    private SysCacheService cacheService;

    private PathMatcher pathMatcher;

    private SecurityProperties properties;

    private SysUserService userService;

    private SysPermissionService permissionService;



    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
            throws ServletException, IOException {
        //直接放行忽视路径
        /** String path = request.getServletPath();
        for(String ignore : properties.getIgnores())
            if(pathMatcher.match(path,ignore)){
                filterChain.doFilter(request,response);
                return;
            }*/
        //获取token
        String head = properties.getToken().getHeader();
        String prefix = properties.getToken().getPrefix();
        String token = request.getHeader(head);
        if(StrUtil.isEmpty(token)||!token.startsWith(prefix)){
            filterChain.doFilter(request,response);
            return;
        }
        //获取用户信息
        token = StrUtil.removePrefix(token,prefix);
        Long userId = JwtUtil.validateToken(token);
        String cacheToken = cacheService.getLogin(userId);
        if(Objects.isNull(cacheToken)||!StrUtil.equals(token,cacheToken)){
            filterChain.doFilter(request,response);
            return;
        }
        //认证信息存入security上下文
        UserVo userVo = userService.getUserById(userId);
        List<String> permission = permissionService.getByUserId(userId);
        SysUserDetails user = new SysUserDetails(userVo,permission);
        UsernamePasswordAuthenticationToken authentication =
                new UsernamePasswordAuthenticationToken(user,null,user.getAuthorities());
        SecurityContextHolder.getContext().setAuthentication(authentication);
        filterChain.doFilter(request,response);
    }
}
